import math
import datetime

from flask import Blueprint, request
from sqlalchemy import null
from sqlalchemy.exc import SQLAlchemyError

from extension import db
from models import Book, Category, Recommend, Borrow
from response import success_response, error_response
from openai_api import get_responses_GPT

books_bp = Blueprint('books', __name__)


@books_bp.route('/api/books/ponsale', methods=['POST', ])
def ponsale():
    book = Book()
    book.bookId = 0
    book.bookName = request.json.get('bookName')
    book.author = request.json.get('author')
    book.ISBN = request.json.get('ISBN')
    book.category = request.json.get('category')
    book.quantity = request.json.get('quantity')
    book.owner = request.json.get('owner')
    book.description = request.json.get('description')
    book.price = request.json.get('price')
    book.press = request.json.get('press')
    db.session.add(book)
    try:
        db.session.commit()
        return success_response()
    except SQLAlchemyError as e:
        db.session.rollback()
        return error_response()


@books_bp.route('/api/books/admin/category', methods=['POST', ])
def addCategory():
    category = Category()
    category.categoryName = request.json.get('categoryName')
    category.categoryId = 0
    db.session.add(category)
    try:
        db.session.commit()
        return success_response()
    except SQLAlchemyError as e:
        db.session.rollback()
        return error_response()


@books_bp.route('/api/books/category', methods=['GET', ])
def getCategories():
    try:
        result = [row.categoryName for row in Category.query.all()]
        return {
            "code": "SUCCESS",
            "message": "SUCCESS",
            "data": {
                "categoryNames": result
            }
        }
    except SQLAlchemyError as e:
        db.session.rollback()
        return error_response()


@books_bp.route('/api/books/bookInfo/<bookId>', methods=['GET', ])
def getBookInfo(bookId):
    try:
        book = Book.query.get(bookId)
        if book:
            return {
                "code": "SUCCESS",
                "message": "SUCCESS",
                "data": {
                    "book": {
                        "bookId": book.bookId,
                        "bookName": book.bookName,
                        "author": book.author,
                        "ISBN": book.ISBN,
                        "category": book.category,
                        "quantity": book.quantity,
                        "owner": book.owner,
                        "description": book.description,
                        "price": book.price,
                        "press": book.press
                    }
                }
            }
        else:
            return {
                "code": "ERROR",
                "message": "ERROR",
                "data": {
                    "book": null
                }
            }
    except SQLAlchemyError as e:
        db.session.rollback()
        return error_response()


@books_bp.route('/api/books/bookList/<categoryName>/<int:page>', methods=['GET', ])
def getBookList(categoryName, page):
    try:
        per_page = 8
        if categoryName == '全部':
            books = Book.query.paginate(page=page, per_page=per_page, error_out=False)
        else:
            books = Book.query.filter_by(category=categoryName).paginate(page=page, per_page=per_page, error_out=False)
        result = [
            {
                "bookName": book.bookName,
                'author': book.author,
                'ISBN': book.ISBN,
                'bookId': book.bookId,
                'quantity': book.quantity
            } for book in books.items
        ]
        return {
            "code": "SUCCESS",
            "message": "SUCCESS",
            "data": {
                "books": result
            }
        }
    except SQLAlchemyError as e:
        db.session.rollback()
        return error_response()


@books_bp.route('/api/books/admin/updateQty/<bookId>', methods=['PUT', ])
def updateQty(bookId):
    newQty = request.form.get('quantity')
    try:
        book = Book.query.get(bookId)
        if book:
            book.quantity = newQty
            db.session.commit()
            return success_response()
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/admin/updateBookInfo/<bookName>', methods=['POST', ])
def updateBookInfo(bookName):
    try:
        book = Book.query.filter_by(bookName=bookName).first()
        if book:
            book.bookName = request.json.get('bookName')
            book.author = request.json.get('author')
            book.ISBN = request.json.get('ISBN')
            book.category = request.json.get('category')
            book.quantity = request.json.get('quantity')
            book.owner = request.json.get('owner')
            book.description = request.json.get('description')
            db.session.commit()
            return success_response()
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/deleteBook/<bookId>', methods=['DELETE', ])
def deleteBook(bookId):
    try:
        book = Book.query.filter_by(bookId=bookId).first()
        if book:
            db.session.delete(book)
            db.session.commit()
            return success_response()
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/admin/deleteCategory/<categoryName>', methods=['DELETE', ])
def deleteCategory(categoryName):
    try:
        category = Category.query.filter_by(categoryName=categoryName).first()
        if category:
            db.session.delete(category)
            db.session.commit()
            return success_response()
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/userBookList/<username>/<int:page>', methods=['GET', ])
def userBookList(username, page):
    try:
        per_page = 8
        books = Book.query.filter_by(owner=username).paginate(page=page, per_page=per_page, error_out=False)
        if books:
            result = [
                {
                    "bookName": book.bookName,
                    "author": book.author,
                    "ISBN": book.ISBN,
                    "bookId": book.bookId,
                    "quantity": book.quantity
                } for book in books
            ]
            return {
                "code": "SUCCESS",
                "message": "SUCCESS",
                "data": {"books": result}
            }
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/searchByBookName/<bookName>/<int:page>', methods=['GET', ])
def searchByBookName(bookName, page):
    try:
        per_page = 10
        books = Book.query.filter(Book.bookName.like(f'%{bookName}%')).paginate(page=page, per_page=per_page,
                                                                                error_out=False)
        if books:
            result = [
                {
                    "bookName": book.bookName,
                    "author": book.author,
                    "ISBN": book.ISBN,
                    "bookId": book.bookId,
                    "quantity": book.quantity
                } for book in books
            ]
            return {
                "code": "SUCCESS",
                "message": "SUCCESS",
                "data": {"books": result}
            }
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/pageNumber/<name>/<int:type>', methods=['GET'])
def pageNumber(name, type):
    try:
        if type == 1:
            if name == '全部':
                books = Book.query.all()
            else:
                books = Book.query.filter_by(category=name).all()
        if type == 2:
            books = Book.query.filter(Book.bookName.like(f'%{name}%')).all()
        if type == 3:
            books = Book.query.filter_by(owner=name).all()
        if books:
            return {
                "code": "SUCCESS",
                "message": "SUCCESS",
                "data": math.floor(len(books) / 10) + 1
            }
        else:
            return error_response()
    except SQLAlchemyError as e:
        return error_response()


@books_bp.route('/api/books/recommend', methods=['GET'])
def recommend():
    today = datetime.date.today()
    firstRecord = Recommend.query.first()
    interval = today - firstRecord.getTime
    days = interval.days
    #days>3，清空表的数据，然后更新表
    if days > 3:
        #包含所有bookName的列表
        books = Book.query.with_entities(Book.bookName).all()
        book_names = [book.bookName for book in books]
        talk = "以下是我图书馆中所有图书列表："
        for bookName in book_names:
            talk += "[" + bookName + "]"
        talk += "以下是图书馆借阅历史记录："
        borrowBooks = Borrow.query.with_entities(Borrow.bookName).all()
        borrowBook_names = [borrowBook.bookName for borrowBook in borrowBooks]
        for borrowBookName in borrowBook_names:
            talk += "[" + borrowBookName + "]"
        talk += ("请你根据以上记录，为我们推荐三本图书馆中的图书。要求输出格式如下：[推荐图书1],[推荐图书2],[推荐图书3]，"
                 "不要有其他多余的话，只需要输出[推荐图书1],[推荐图书2],[推荐图书3],请严格根据输出格式进行输出。")
        response = get_responses_GPT(talk, histories=[])
        if response:
            recommendList = response.strip("[]").split("],[")
            resultList = []
            db.session.query(Recommend).delete()
            db.session.commit()
            for recommend in recommendList:
                book = Book.query.filter_by(bookName=recommend).first()
                if book:
                    resultList.append({
                        "bookName": book.bookName,
                        "author": book.author,
                        "bookId": book.bookId,
                    })
                    recommend = Recommend(bookId=book.bookId, bookName=book.bookName, author=book.author, getTime=today)
                    db.session.add(recommend)
                    db.session.commit()

            return {
                "code": "SUCCESS",
                "message": "SUCCESS",
                "data": resultList
            }
        else:
            return {
                "code": "ERROR",
                "message": "ERROR",
                "data": "连接失败，请检查网络连接"
            }
    #days<=3，直接取表里面的数据
    else:
        recommendList = Recommend.query.all()
        resultList = []
        for record in recommendList:
            resultList.append({
                "bookName": record.bookName,
                "bookId": record.bookId,
                "author": record.author
            })
        return {
            "code": 0,
            "message": "SUCCESS",
            "data": resultList
        }
